﻿using Microsoft.Win32;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using static DataFile;

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    public class CallerMemberNameAttribute : Attribute { }

    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    public class CallerFilePathAttribute : Attribute { }

    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    public class CallerLineNumberAttribute : Attribute { }
}

namespace TaiwuZD
{
    public class BindableBase : INotifyPropertyChanged
    {

        /// <summary>
        /// 
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="storage"></param>
        /// <param name="value"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        protected bool SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] String propertyName = null)
        {
            if (string.IsNullOrEmpty(propertyName)) return false;
            if (object.Equals(storage, value)) return false;
            try
            {
                storage = value;
                //ThreadPool.QueueUserWorkItem(new WaitCallback(NotifyPropertyChanged), propertyName);

                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="propertyName"></param>
        protected void NotifyPropertyChanged(object propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs((string)propertyName));
            }
        }
    }


    /// <summary>
    /// 全局变量
    /// </summary>
    public class Global : BindableBase
    {
        public static Global Inst { get; private set; } = new Global();



        private bool _IsSFLoaded;
        private string _StorageFilePath;
        private Role _CurrentRole;

        private Global()
        {

            CheckTaiwuDirectory();


            //loadItems();
        }


        public string FontName { get; set; } = "等线";

        public string TaiwuStoragePath { get; private set; }


        /// <summary>
        /// 存档位置
        /// </summary>
        public string StorageFilePath
        {
            get { return _StorageFilePath; }
            set { SetProperty(ref _StorageFilePath, value); ReLoadData(); }
        }

        

        private MemoryStream[] TempSaveFileStream { get; set; }

        /// <summary>
        /// 存档是否加载
        /// </summary>
        public bool IsSFLoaded
        {
            get { return _IsSFLoaded; }
            set { SetProperty(ref _IsSFLoaded, value); }
        }




        /// <summary>
        ///  是否找到app路径
        /// </summary>
        public bool IsTaiwuDirectoryFound { get; private set; } = false;

        /// <summary>
        /// 主角
        /// </summary>
        public Role MajorRole { get; private set; } = new Role();


        public Role CurrentRole
        {
            get { return _CurrentRole; }
            set
            {
                if (_CurrentRole != null)
                    _CurrentRole.PropertyChanged -= CurrentRoleDataChanged;

                if (value == null) return;

                value.LoadData();
                SetProperty(ref _CurrentRole, value);
                _CurrentRole.PropertyChanged += CurrentRoleDataChanged;

                RoleChanged.Add(value);
            }
        }


        private Role[] _AllRoles;

        public Role[] AllRoles
        {
            get { return _AllRoles; }
            set { SetProperty(ref _AllRoles, value); }
        }

        private HashSet<Role> RoleChanged { get; set; } = new HashSet<Role>();


        private int _BuildingUpperLimit;

        /// <summary>
        /// 村子建筑上限
        /// </summary>
        public int BuildingUpperLimit
        {
            get { return _BuildingUpperLimit; }
            set { SetProperty(ref _BuildingUpperLimit, value); }
        }

        /// <summary>
        /// 新物品序号
        /// </summary>
        private int NewItemIndex { get; set; }


        public WorldEnvironment World { get; private set; } = new WorldEnvironment();

        private ObservableCollection<TwBuilding> _HomeBuildingMap;

        public ObservableCollection<TwBuilding> HomeBuildingMap
        {
            get { return _HomeBuildingMap; }
            private set { SetProperty(ref _HomeBuildingMap, value); }
        }


        public string[] BuildingTypes { get; } = { "资源", "采集", "主建筑", "练功房", "琴舍", "弈轩", "书房", "画阁", "观星台", "甘泉厅", "火炼室", "木工房", "药房", "幽室", "绣楼", "巧匠屋", "云房", "禅房", "食窖", "长街", };

 


        private void CheckTaiwuDirectory()
        {
            try
            {
                var rkey = Registry.CurrentUser.OpenSubKey(@"Software\Valve\Steam");
                if (rkey != null)
                {
                    var path = rkey.GetValue("SteamPath").ToString().Replace('/', '\\') + "\\";
                    path = Path.Combine(path, @"steamapps\common\The Scroll Of Taiwu\The Scroll Of Taiwu Alpha V1.0_Data\SaveFiles");

                    IsTaiwuDirectoryFound = Directory.Exists(path);
                    if (IsTaiwuDirectoryFound)
                        TaiwuStoragePath = path;
                }
            }
            catch (Exception er)
            {

                //throw;
            }
        }


        internal TwItem CreateNewItem(int id,int am =1 )
        {
            TwItem r = new TwItem(id);

            r.Amount = am;
            r.Key = ++NewItemIndex;

            

            return r;
        }



        /// <summary>
        /// 重新载入存档数据
        /// </summary>
        private void ReLoadData()
        {
            SD = null;
            HBD = null;
            this.CurrentRole = null;
            this.AllRoles = null;
            this.HomeBuildingMap = new ObservableCollection<TwBuilding>();
            this.MajorRole = new Role();
            RoleChanged.Clear();

            Copy2TempFile();

            if (TempSaveFileStream[0] != null)
                LoadSaveData();
            if (TempSaveFileStream[1] != null)
                LoadWorldEnvironment();
            if (TempSaveFileStream[2] != null)
                LoadHomeData();

            //var fp = TempSaveFile[0];//Path.Combine(StorageFilePath, "TW_Save_Date_0.tw");
            //if (File.Exists(fp))
            //{
            //    LoadSaveData(fp);
            //}

            //fp = TempSaveFile[2];//Path.Combine(StorageFilePath, "TW_Save_Date_2.tw");
            //if (File.Exists(fp))
            //{
            //    HBD = LoadHomeData(fp);
            //    LoadHomeBuildings();
            //}

            //fp = TempSaveFile[1];//Path.Combine(StorageFilePath, "TW_Save_Date_1.tw");
            //if (File.Exists(fp))
            //{
            //    LoadWorldEnvironment(fp);
            //}

            IsSFLoaded = true;
        }

        private void Copy2TempFile()
        { 
            TempSaveFileStream = new MemoryStream[9];
            for (int i = 0; i < 9; i++)
            { 
                var fp = Path.Combine(StorageFilePath, $"TW_Save_Date_{i}.tw"); 

                TempSaveFileStream[i] = new MemoryStream();
                using (var fs = File.OpenRead(fp))
                {
                    fs.CopyTo(TempSaveFileStream[i]);
                } 
            } 
        }

        public HomeBuildingData LoadHomeData(string path)
        {
            return (DataFile.HomeBuildingData)GetData(path, typeof(DataFile.HomeBuildingData));
        }

        private void LoadHomeData()
        {
            HBD = (DataFile.HomeBuildingData)GetData(TempSaveFileStream[2], typeof(DataFile.HomeBuildingData));

            int p_partId = SD._partId;
            int p_placeId = SD._placeId;
            if (!HBD._homeBuildingsData.ContainsKey(p_partId))
                return;
            if (!HBD._homeBuildingsData[p_partId].ContainsKey(p_placeId))
            {
                p_placeId = HBD._homeBuildingsData[p_partId].OrderBy(x => Math.Abs(x.Key - p_partId)).First().Key;
            }

            var val = HBD._homeBuildingsData[p_partId][p_placeId];

            var mm = new TwBuilding[169];
            for (int i = 0; i < val.Count; i++)
            {
                mm[i] = TwBuilding.Create(val[i][0], val[i][1]);
            }
            HomeBuildingMap = new ObservableCollection<TwBuilding>(mm);
        }

        private void LoadSaveData(string filepath)
        {
            SD = (DataFile.SaveData)GetData(filepath, typeof(DataFile.SaveData));
            List<Role> all = new List<Role>();

            foreach (int key2 in SD._actorsData.Keys)
            {
                if (SD._actorsData[key2].Keys.Contains(5) && SD._actorsData[key2].Keys.Contains(0))
                {
                    //actors_list.Add(new CBItem(key2 + " " + SD._actorsData[key2][5] + SD._actorsData[key2][0], key2));
                    all.Add(new Role { Id = key2, FirstName = SD._actorsData[key2][5], LastName = SD._actorsData[key2][0] });
                }
                else if (SD._actorsData[key2].Keys.Contains(0) && SD._actorsData[key2].Keys.Contains(29))
                {
                    int key = int.Parse(SD._actorsData[key2][29]);
                    //actors_list.Add(new CBItem(key2 + " " + GameAssets.ActorSurNames[key] + SD._actorsData[key2][0], key2));
                    all.Add(new Role { Id = key2, FirstName = GameAssets.ActorSurNames[key], LastName = SD._actorsData[key2][0] });
                }
            }

            AllRoles = all.ToArray();
            MajorRole = all.First();
            CurrentRole = MajorRole;
            //loadSX();
            BuildingUpperLimit = SD._homeFavorAdd;

            //loadActorsBySearch("");
        }
        private void LoadSaveData()
        {
            SD = (DataFile.SaveData)GetData(TempSaveFileStream[0], typeof(DataFile.SaveData));
            List<Role> all = new List<Role>();

            foreach (int key2 in SD._actorsData.Keys)
            {
                if (SD._actorsData[key2].Keys.Contains(5) && SD._actorsData[key2].Keys.Contains(0))
                { 
                    all.Add(new Role { Id = key2, FirstName = SD._actorsData[key2][5], LastName = SD._actorsData[key2][0] });
                }
                else if (SD._actorsData[key2].Keys.Contains(0) && SD._actorsData[key2].Keys.Contains(29))
                {
                    int key = int.Parse(SD._actorsData[key2][29]); 
                    all.Add(new Role { Id = key2, FirstName = GameAssets.ActorSurNames[key], LastName = SD._actorsData[key2][0] });
                }
            }

            NewItemIndex = SD._newItemId;
            AllRoles = all.ToArray();
            MajorRole = AllRoles.FirstOrDefault(x=>x.Id == SD._mianActorId);
            CurrentRole = MajorRole; 
            BuildingUpperLimit = SD._homeFavorAdd;
        }

      

        public void LoadWorldEnvironment(string path)
        {
            WE = (GameSetting)GetData(path, typeof(GameSetting));
            World.AgeTime = WE._ageTime;
            World.BirthWorldId = WE._birthWorldId;
            World.EnemyBorn = WE._enemyBorn;
            World.EnemySize = WE._enemySize;
            World.HomeTypeId = WE._homeTypId;
            World.RandomHeir = WE._randomHeir == 0 ? true : false;
            World.WorldResource = WE._worldResource;
            World.xxLevel = WE._xxLevel;
        }
        public void LoadWorldEnvironment( )
        {
            WE = (GameSetting)GetData(TempSaveFileStream[1], typeof(GameSetting));
            World.AgeTime = WE._ageTime;
            World.BirthWorldId = WE._birthWorldId;
            World.EnemyBorn = WE._enemyBorn;
            World.EnemySize = WE._enemySize;
            World.HomeTypeId = WE._homeTypId;
            World.RandomHeir = WE._randomHeir == 0 ? true : false;
            World.WorldResource = WE._worldResource;
            World.xxLevel = WE._xxLevel;
        }


        public void SaveWorldEnvironment()
        {
            if (WE == null) return;

            WE._ageTime = World.AgeTime;
            WE._birthWorldId = World.BirthWorldId;
            WE._enemyBorn = World.EnemyBorn;
            WE._enemySize = World.EnemySize;
            WE._homeTypId = World.HomeTypeId;
            WE._randomHeir = World.RandomHeir ? 0 : 1;
            WE._worldResource = World.WorldResource;
            WE._xxLevel = World.xxLevel;
        }

        public object GetData(string fileName, Type pType)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            byte[] array = File.ReadAllBytes(fileName);
            if (array[0] == 95 && array[1] == 115 && array[2] == 68 && array[3] == 65 && array[4] == 84 && array[5] == 65)
            {
                DataFile.SaveData saveData = new DataFile.SaveData();
                saveData.Load(array);
                stopwatch.Stop();
                return saveData;
            }
            object result = _oldGetData(fileName, pType);
            stopwatch.Stop();
            return result;
        }
        public object _oldGetData(string fileName, Type pType)
        {
            StreamReader streamReader = File.OpenText(fileName);
            string pString = streamReader.ReadToEnd();
            pString = RijndaelDecrypt(pString, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            streamReader.Close();
            return DeserializeObject(pString, pType);
        }
        private void SetData(string fileName, object pObject)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            if (pObject.GetType() == typeof(DataFile.ActorLife))
            {
                byte[] bytes = ((DataFile.ActorLife)pObject).SaveV1();
                File.WriteAllBytes(fileName, bytes);
                stopwatch.Stop();
            }
            else if (pObject.GetType() == typeof(DataFile.SaveData))
            {
                byte[] bytes2 = ((DataFile.SaveData)pObject).SaveV1();
                File.WriteAllBytes(fileName, bytes2);
                stopwatch.Stop();
            }
            else
            {
                _oldSetData(fileName, pObject);
            }
        }

        private void _oldSetData(string fileName, object pObject)
        {
            string pString = SerializeObject(pObject);
            pString = RijndaelEncrypt(pString, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

            StreamWriter streamWriter = File.CreateText(fileName);
            streamWriter.Write(pString);
            streamWriter.Flush();
            streamWriter.Close();
        }

        public object GetData(Stream stream, Type pType)
        {
            stream.Seek(0, SeekOrigin.Begin);
            byte[] array = new byte[stream.Length];
            stream.Read(array, 0, (int)stream.Length);
            if (array[0] == 95 && array[1] == 115 && array[2] == 68 && array[3] == 65 && array[4] == 84 && array[5] == 65)
            {
                DataFile.SaveData saveData = new DataFile.SaveData();
                saveData.Load(array); 
                return saveData;
            }
            object result = _oldGetData(stream, pType); 
            return result;
        }
        public object _oldGetData(Stream stream, Type pType)
        {
            stream.Seek(0, SeekOrigin.Begin);
            StreamReader streamReader = new StreamReader(stream); 
            string pString = streamReader.ReadToEnd();
            pString = RijndaelDecrypt(pString, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            //streamReader.Close();
            return DeserializeObject(pString, pType);
        }
        

        private string SerializeObject(object pObject)
        {
            return JsonConvert.SerializeObject(pObject);
        }
        private object DeserializeObject(string pString, Type pType)
        {
            return JsonConvert.DeserializeObject(pString, pType);
        }



        private void CurrentRoleDataChanged(object sender, PropertyChangedEventArgs e)
        {
            var actor = SD._actorsData[CurrentRole.Id];
            switch (e.PropertyName)
            {
                case nameof(Role.FirstName):

                    break;
            }
        }



        private string RijndaelDecrypt(string pString, string pKey)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(pKey);
            byte[] array = Convert.FromBase64String(pString);
            byte[] bytes2 = new RijndaelManaged
            {
                Key = bytes,
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            }.CreateDecryptor().TransformFinalBlock(array, 0, array.Length);
            return Encoding.UTF8.GetString(bytes2);
        }

        private string RijndaelEncrypt(string pString, string pKey)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(pKey);
            byte[] bytes2 = Encoding.UTF8.GetBytes(pString);
            byte[] array = new RijndaelManaged
            {
                Key = bytes,
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            }.CreateEncryptor().TransformFinalBlock(bytes2, 0, bytes2.Length);
            return Convert.ToBase64String(array, 0, array.Length);
        }



        private static int GetRandomSeed()
        {
            byte[] array = new byte[4];
            new RNGCryptoServiceProvider().GetBytes(array);
            return BitConverter.ToInt32(array, 0);
        }
        //private void ChangeNewItemSPower(int baseItemId, int itemId, int powerId)
        //{
        //    int num = GameAssets.TwItemPowers[powerId].ValueAt<int>(902);
        //    int num2 = GameAssets.TwItemPowers[powerId].ValueAt<int>(501);
        //    int num3 = GameAssets.TwItemPowers[powerId].ValueAt<int>(601);
        //    int num4 = GameAssets.TwItemPowers[powerId].ValueAt<int>(603);
        //    int num5 = GameAssets.TwItemPowers[powerId].ValueAt<int>(904);
        //    int num6 = GameAssets.TwItemPowers[powerId].ValueAt<int>(905);
        //    if (num != 0)
        //    {
        //        int num7 = Math.Max(int.Parse(GetItemDate(itemId, 902, true)) * (100 + num) / 100, 1);
        //        SD._itemsData[itemId][901] = num7.ToString();
        //        SD._itemsData[itemId][902] = num7.ToString();
        //    }
        //    int num8;
        //    if (num2 != 0)
        //    {
        //        Dictionary<int, string> dictionary = SD._itemsData[itemId];
        //        num8 = Math.Max(int.Parse(GameAssets.TwItems[baseItemId][501]) * (100 + num2) / 100, 1);
        //        dictionary[501] = num8.ToString();
        //    }
        //    if (num3 != 0)
        //    {
        //        Dictionary<int, string> dictionary2 = SD._itemsData[itemId];
        //        num8 = Math.Max(int.Parse(GameAssets.TwItems[baseItemId][601]) * (100 + num3) / 100, 1);
        //        dictionary2[601] = num8.ToString();
        //    }
        //    if (num4 != 0)
        //    {
        //        Dictionary<int, string> dictionary3 = SD._itemsData[itemId];
        //        num8 = Math.Max(int.Parse(GameAssets.TwItems[baseItemId][603]) * (100 + num4) / 100, 1);
        //        dictionary3[603] = num8.ToString();
        //    }
        //    if (num5 != 0)
        //    {
        //        Dictionary<int, string> dictionary4 = SD._itemsData[itemId];
        //        num8 = Math.Max(int.Parse(GameAssets.TwItems[baseItemId][904]) * (100 + num5) / 100, 1);
        //        dictionary4[904] = num8.ToString();
        //    }
        //    if (num6 != 0)
        //    {
        //        Dictionary<int, string> dictionary5 = SD._itemsData[itemId];
        //        num8 = Math.Max(int.Parse(GameAssets.TwItems[baseItemId][905]) * (100 + num6) / 100, 1);
        //        dictionary5[905] = num8.ToString();
        //    }
        //    SD._itemsData[itemId][504] = powerId.ToString();
        //}

        //public void SetBookPage(int id, int bookObbs = 0, int pageSize = 0)
        //{
        //    int[] array = new int[10];
        //    if (pageSize > 0)
        //    {
        //        int num = 0;
        //        int num2 = 10;
        //        if (GetRandomByGuid(0, 100) < 90 + bookObbs)
        //        {
        //            pageSize--;
        //            num = 1;
        //            num2 = 9;
        //            array[0] = 1;
        //        }
        //        if (pageSize > 0)
        //        {
        //            List<int> list = new List<int>();
        //            for (int i = 0; i < num2; i++)
        //            {
        //                list.Add(0);
        //            }
        //            for (int j = 0; j < pageSize; j++)
        //            {
        //                list[j] = 1;
        //            }
        //            for (int k = num; k < 10; k++)
        //            {
        //                int randomByGuid = GetRandomByGuid(0, list.Count);
        //                array[k] = list[randomByGuid];
        //                list.Remove(list[randomByGuid]);
        //            }
        //        }
        //    }
        //    else
        //    {
        //        if (GetRandomByGuid(0, 100) < 90 + bookObbs)
        //        {
        //            array[0] = 1;
        //        }
        //        else
        //        {
        //            array[GetRandomByGuid(0, array.Length)] = 1;
        //        }
        //        for (int l = 0; l < 10; l++)
        //        {
        //            if (GetRandomByGuid(0, 100) < 60 + bookObbs)
        //            {
        //                array[l] = 1;
        //            }
        //        }
        //    }
        //    SD._itemsData[id][33] = string.Join("|", array);// $"{array[0]}|{array[1]}|{array[2]}|{array[3]}|{array[4]}|{array[5]}|{array[6]}|{array[7]}|{array[8]}|{array[9]}";
        //}

        //public int MakeNewItem(int id, int temporaryId = 0, int bookObbs = 0, int buffObbs = 50, int sBuffObbs = 20)
        //{
        //    int num = 0;
        //    Dictionary<int, string> value = new Dictionary<int, string>();
        //    if (temporaryId < 0)
        //    {
        //        num = temporaryId;
        //        SD._itemsData.Remove(temporaryId);
        //        SD._itemsChangeData.Remove(temporaryId);
        //    }
        //    else
        //    {
        //        do
        //        {
        //            SD._newItemId++;
        //        }
        //        while (SD._itemsData.Keys.Contains(SD._newItemId));
        //        num = SD._newItemId;
        //    }
        //    SD._itemsData.Add(num, value);
        //    SD._itemsData[num][999] = id.ToString();
        //    bool flag = int.Parse(presetitemData[id][5]) != 36;
        //    int num2 = ((int.Parse(presetitemData[id][5]) == 34 || int.Parse(presetitemData[id][5]) == 35) && int.Parse(presetitemData[id][6]) != 1) ? 20 : 0;
        //    int num3 = flag ? int.Parse(presetitemData[id][1]) : 0;
        //    int num4 = int.Parse(presetitemData[id][902]);
        //    int num5;
        //    if (num4 > 0)
        //    {
        //        if (flag)
        //        {
        //            num4 = 1 + num4 * GetRandomByGuid(50, 101) / 100;
        //        }
        //        SD._itemsData[num][902] = num4.ToString();
        //        SD._itemsData[num][901] = num4.ToString();
        //    }
        //    else if (num4 < 0)
        //    {
        //        Dictionary<int, string> dictionary = SD._itemsData[num];
        //        num5 = Math.Abs(num4);
        //        dictionary[902] = num5.ToString();
        //        Dictionary<int, string> dictionary2 = SD._itemsData[num];
        //        num5 = Math.Abs(num4);
        //        dictionary2[901] = num5.ToString();
        //    }
        //    switch (num3)
        //    {
        //        case 1:
        //            {
        //                if (int.Parse(presetitemData[id][606]) > 0)
        //                {
        //                    string text = "";
        //                    List<string> list2 = new List<string>(presetitemData[id][7].Split('|'));
        //                    int count = list2.Count;
        //                    for (int i = 0; i < count; i++)
        //                    {
        //                        int randomByGuid = GetRandomByGuid(0, list2.Count);
        //                        text += ((i != 0) ? ("|" + list2[randomByGuid]) : list2[randomByGuid]);
        //                        list2.Remove(list2[randomByGuid]);
        //                    }
        //                    SD._itemsData[num][7] = text;
        //                }
        //                if (GetRandomByGuid(0, 100) < buffObbs)
        //                {
        //                    int num6 = GetRandomByGuid(0, 3) + 1;
        //                    if (buffObbs == 999)
        //                    {
        //                        num6 *= 100;
        //                    }
        //                    SD._itemsData[num][505] = num6.ToString();
        //                }
        //                int num7 = int.Parse(presetitemData[id][504]);
        //                if (num7 != 0 && GetRandomByGuid(0, 100) < sBuffObbs)
        //                {
        //                    List<int> list3 = new List<int> { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 401, 402, 403, 404, 407 };
        //                    if (num7 < 0)
        //                    {
        //                        list3.Add(Math.Abs(num7));
        //                    }
        //                    int num8 = int.Parse(presetitemData[id][506]);
        //                    if (num8 != 0)
        //                    {
        //                        list3.Add(209 + num8);
        //                    }
        //                    ChangeNewItemSPower(id, num, list3[GetRandomByGuid(0, list3.Count)]);
        //                }
        //                break;
        //            }
        //        case 2:
        //            if (GetRandomByGuid(0, 100) < buffObbs)
        //            {
        //                Dictionary<int, string> dictionary3 = SD._itemsData[num];
        //                int key = 51361 + GetRandomByGuid(0, 6);
        //                num5 = Math.Max(int.Parse(presetitemData[id][8]) / 2, 1) * ((buffObbs != 999) ? 5 : 10);
        //                dictionary3[key] = num5.ToString();
        //            }
        //            if (GetRandomByGuid(0, 100) < sBuffObbs)
        //            {
        //                List<int> list4 = new List<int>
        //            {
        //                401,
        //                402,
        //                405,
        //                406,
        //                407
        //            };
        //                ChangeNewItemSPower(id, num, list4[GetRandomByGuid(0, list4.Count)]);
        //            }
        //            break;
        //        case 3:
        //            num2 = ((buffObbs != 999) ? 5 : 10);
        //            if (GetRandomByGuid(0, 100) < sBuffObbs)
        //            {
        //                List<int> list = new List<int>
        //            {
        //                407
        //            };
        //                ChangeNewItemSPower(id, num, list[GetRandomByGuid(0, list.Count)]);
        //            }
        //            break;
        //    }
        //    if (num2 != 0 && GetRandomByGuid(0, 100) < buffObbs)
        //    {
        //        if (GetRandomByGuid(0, 100) < 50)
        //        {
        //            Dictionary<int, string> dictionary4 = SD._itemsData[num];
        //            int key2 = 50501 + GetRandomByGuid(0, 16);
        //            num5 = Math.Max(int.Parse(presetitemData[id][8]) / 2, 1) * num2;
        //            dictionary4[key2] = num5.ToString();
        //        }
        //        else
        //        {
        //            Dictionary<int, string> dictionary5 = SD._itemsData[num];
        //            int key3 = 50601 + GetRandomByGuid(0, 14);
        //            num5 = Math.Max(int.Parse(presetitemData[id][8]) / 2, 1) * num2;
        //            dictionary5[key3] = num5.ToString();
        //        }
        //    }
        //    if (int.Parse(presetitemData[id][31]) > 0)
        //    {
        //        SetBookPage(num, bookObbs, 0);
        //    }
        //    return num;
        //}
        ////public string GetItemDate(int id, int index, bool otherMassage = true)
        ////{
        ////    string text = (!presetitemData.ContainsKey(id) || !presetitemData[id].ContainsKey(index)) ? "0" : presetitemData[id][index];
        ////    int key = presetitemData.ContainsKey(id) ? id : 0;
        ////    int num2 = 0;
        ////    if (SD._itemsData.ContainsKey(id))
        ////    {
        ////        if ((index > 50000 /*|| hp0NoGetAttr.Contains(index)) */&& int.Parse(GetItemDate(id, 901, true)) <= 0)
        ////        {
        ////            return "0";
        ////        }
        ////        key = int.Parse(SD._itemsData[id][999]);
        ////        if (SD._itemsData[id].ContainsKey(index))
        ////        {
        ////            text = SD._itemsData[id][index];
        ////        }
        ////        else
        ////        {
        ////            if (!presetitemData[key].ContainsKey(index))
        ////            {
        ////                return "0";
        ////            }
        ////            text = presetitemData[key][index];
        ////        }
        ////        if (int.Parse(presetitemData[key][2001]) == 1)
        ////        {
        ////            int key2 = (!SD._itemsData[id].ContainsKey(2002)) ? int.Parse(presetitemData[key][2002]) : int.Parse(SD._itemsData[id][2002]);
        ////            int num = (!SD._itemsData[id].ContainsKey(2003)) ? int.Parse(presetitemData[key][2003]) : int.Parse(SD._itemsData[id][2003]);
        ////            switch (index)
        ////            {
        ////                case 0:
        ////                    text = ((num <= 0) ? cricketData[key2][0] : ((int.Parse(cricketData[key2][2]) < int.Parse(cricketData[num][2])) ? (cricketData[num][0] + cricketData[key2][0].Split('|')[1]) : (cricketData[key2][0].Split('|')[0] + cricketData[num][0])));
        ////                    break;
        ////                case 8:
        ////                    num2 = GetQuquDate(id, 1, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////                case 98:
        ////                    text = cricketData[key2][97];
        ////                    break;
        ////                case 99:
        ////                    text = ((num <= 0) ? cricketData[key2][99] : cricketData[num][99]);
        ////                    break;
        ////                case 904:
        ////                    num2 = GetQuquDate(id, 94, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////                case 905:
        ////                    num2 = GetQuquDate(id, 95, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////                case 52001:
        ////                    num2 = GetQuquDate(id, index, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////                case 52002:
        ////                    num2 = GetQuquDate(id, index, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////                case 52003:
        ////                    num2 = GetQuquDate(id, index, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////                case 52004:
        ////                    num2 = GetQuquDate(id, index, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////                case 52005:
        ////                    num2 = GetQuquDate(id, index, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////                case 52006:
        ////                    num2 = GetQuquDate(id, index, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////                case 52007:
        ////                    num2 = GetQuquDate(id, index, true);
        ////                    text = num2.ToString();
        ////                    break;
        ////            }
        ////        }
        ////    }
        ////    if (otherMassage)
        ////    {
        ////        switch (index)
        ////        {
        ////            case 0:
        ////                text += SetItemName(id);
        ////                break;
        ////            case 801:
        ////                if (int.Parse(GetItemDate(id, 505, true)) == 1)
        ////                {
        ////                    num2 = int.Parse(text) + int.Parse(presetitemData[key][8]) * 5;
        ////                    text = num2.ToString();
        ////                }
        ////                if (int.Parse(GetItemDate(id, 505, true)) == 100)
        ////                {
        ////                    num2 = int.Parse(text) + int.Parse(presetitemData[key][8]) * 10;
        ////                    text = num2.ToString();
        ////                }
        ////                break;
        ////            case 802:
        ////                if (int.Parse(GetItemDate(id, 505, true)) == 2)
        ////                {
        ////                    num2 = int.Parse(text) + int.Parse(presetitemData[key][8]) * 5;
        ////                    text = num2.ToString();
        ////                }
        ////                if (int.Parse(GetItemDate(id, 505, true)) == 200)
        ////                {
        ////                    num2 = int.Parse(text) + int.Parse(presetitemData[key][8]) * 10;
        ////                    text = num2.ToString();
        ////                }
        ////                break;
        ////            case 803:
        ////                if (int.Parse(GetItemDate(id, 505, true)) == 3)
        ////                {
        ////                    num2 = int.Parse(text) + int.Parse(presetitemData[key][8]) * 5;
        ////                    text = num2.ToString();
        ////                }
        ////                if (int.Parse(GetItemDate(id, 505, true)) == 300)
        ////                {
        ////                    num2 = int.Parse(text) + int.Parse(presetitemData[key][8]) * 10;
        ////                    text = num2.ToString();
        ////                }
        ////                break;
        ////            case 804:
        ////                if (int.Parse(GetItemDate(id, 505, true)) == 4)
        ////                {
        ////                    num2 = int.Parse(text) + int.Parse(presetitemData[key][8]) * 5;
        ////                    text = num2.ToString();
        ////                }
        ////                if (int.Parse(GetItemDate(id, 505, true)) == 400)
        ////                {
        ////                    num2 = int.Parse(text) + int.Parse(presetitemData[key][8]) * 10;
        ////                    text = num2.ToString();
        ////                }
        ////                break;
        ////        }
        ////    }
        ////    if (SD._itemsChangeData.ContainsKey(id) && SD._itemsChangeData[id].ContainsKey(index))
        ////    {
        ////        num2 = int.Parse(text) + SD._itemsChangeData[id][index] / 10;
        ////        text = num2.ToString();
        ////    }
        ////    if (hpDownAttrDown.Contains(index))
        ////    {
        ////        int num3 = int.Parse(GetItemDate(id, 901, true));
        ////        int num4 = int.Parse(GetItemDate(id, 902, true));
        ////        if (num3 < num4)
        ////        {
        ////            int num5 = int.Parse(text);
        ////            num2 = ((num3 > 0) ? (num5 - num5 * 50 / 100 * (100 - num3 * 100 / num4) / 100) : 0);
        ////            text = num2.ToString();
        ////        }
        ////    }
        ////    if (index == 501 && int.Parse(presetitemData[key][501]) != 0)
        ////    {
        ////        num2 = Math.Max(int.Parse(text), 10);
        ////        text = num2.ToString();
        ////    }
        ////    return text;
        ////}

        //public int AddItem(int actorId, int itemId, int itemNumber, bool newItem, int getTypIndex = -1, int bookObbs = 0)
        //{
        //    if (itemId <= 0 || itemNumber <= 0 || GameAssets.TwItems[itemId].ValueAt<int>(4) /*int.Parse(  GetItemDate(itemId, 4, true))*/ <= 0)
        //    {
        //        return 0;
        //    }
        //    if (newItem && int.Parse(presetitemData[itemId][6]) == 0)
        //    {
        //        for (int i = 0; i < itemNumber; i++)
        //        {
        //            itemId = MakeNewItem(itemId, 0, bookObbs, 50, 20);
        //            SD._actorItemsData[actorId].Add(itemId, 1);
        //        }
        //    }
        //    else if (/*int.Parse(GetItemDate(itemId, 6, true)*/GameAssets.TwItems[itemId].ValueAt<int>(6) == 0)
        //    {
        //        if (!SD._actorItemsData[actorId].ContainsKey(itemId))
        //        {
        //            SD._actorItemsData[actorId].Add(itemId, 1);
        //        }
        //    }
        //    else if (SD._actorItemsData[actorId].ContainsKey(itemId))
        //    {
        //        SD._actorItemsData[actorId][itemId] = SD._actorItemsData[actorId][itemId] + itemNumber;
        //    }
        //    else
        //    {
        //        SD._actorItemsData[actorId].Add(itemId, itemNumber);
        //    }
        //    return itemId;
        //}


        public SaveData SD { get; set; }

        public DataFile.HomeBuildingData HBD { get; set; }
        public GameSetting WE { get; private set; }

        public void DestroyBuilding(int place)
        {
            var nb = TwBuilding.Create();
            HomeBuildingMap[place] = nb;

            int p_partId = SD._partId;
            int p_placeId = SD._placeId;

            int key = place;// int.Parse(building_index.Text);
            int num = nb.Id;//int.Parse(building_id.Text);
            int num2 = nb.Level;// int.Parse(building_level.Text);
            int num3 = nb.Category;// int.Parse(building_type.Text);
            HBD._homeBuildingsData[p_partId][p_placeId][key][0] = num;
            HBD._homeBuildingsData[p_partId][p_placeId][key][1] = num2;
            HBD._homeBuildingsData[p_partId][p_placeId][key][2] = num3;
        }

        internal void BuildBuilding(int place, TwBuilding taiwuBuilding)
        {
            var nb = TwBuilding.Create(taiwuBuilding.Id);
            HomeBuildingMap[place] = nb;

            int p_partId = SD._partId;
            int p_placeId = SD._placeId;

            int key = place;// int.Parse(building_index.Text);
            int num = nb.Id;//int.Parse(building_id.Text);
            int num2 = nb.Level;// int.Parse(building_level.Text);
            int num3 = nb.Category;// int.Parse(building_type.Text);
            HBD._homeBuildingsData[p_partId][p_placeId][key][0] = num;
            HBD._homeBuildingsData[p_partId][p_placeId][key][1] = num2;
            HBD._homeBuildingsData[p_partId][p_placeId][key][2] = num3;
        }

        /// <summary>
        /// 备份存档
        /// </summary>
        private void Backup()
        {
            var dir = new DirectoryInfo(StorageFilePath);
            dir = dir.CreateSubdirectory($"Backup\\{DateTime.Now.ToString("yyyyMMdd-HHmmss")}");

            for (int i = 0; i < 9; i++)
            {
                if (TempSaveFileStream[i] == null)
                    continue;

                var fp = Path.Combine(dir.FullName, $"TW_Save_Date_{i}.tw");

                using (var fs = new FileStream(fp, FileMode.Create))
                {
                    TempSaveFileStream[i].Seek(0, SeekOrigin.Begin);
                    TempSaveFileStream[i].CopyTo(fs);
                    fs.Flush();
                }
            } 
        }

        /// <summary>
        /// 保存存档
        /// </summary>
        public void SaveSaveFile()
        {
            if (!IsSFLoaded)
                return;

            Backup();

            foreach (var item in RoleChanged)
            {
                item.SaveData();
            }


            SD._homeFavorAdd = BuildingUpperLimit;


            SetData(Path.Combine(StorageFilePath, "TW_Save_Date_0.tw"), SD);

            SaveWorldEnvironment();
            SetData(Path.Combine(StorageFilePath, "TW_Save_Date_1.tw"), WE);

            SetData(Path.Combine(StorageFilePath, "TW_Save_Date_2.tw"), HBD);
        }
    }
}
